#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/fb.h>
#include <linux/vt.h>
#include <linux/kd.h>
#include <sys/mman.h>
#include <asm/ioctls.h>
#include <errno.h>

#define loge printf

void closetty(char* tty){
	int ttyfd;
	struct vt_stat vts;
	struct vt_mode vt;
	fprintf(stdout, "try to close:%s\n", tty);
	ttyfd = open(tty, O_RDWR);
	if (ttyfd >= 0) {
		if (ioctl(ttyfd, VT_GETMODE, &vt) < 0) {
		      fprintf(stderr, "error: ioctl VT_GETMODE\n");
		  return;
		}
		vts.v_signal = vt.relsig;
		if (ioctl(ttyfd, VT_SENDSIG, &vts) < 0){
			fprintf(stdout, "VT_SENDSIG [%d] failed:%d\n",vt.relsig, errno);
			return;
		}
		ioctl(ttyfd, KDSETMODE, KD_TEXT);
		ioctl(ttyfd, TIOCNOTTY, 0);
		close(ttyfd);
		fprintf(stdout, "close tty:%s\n", tty);
	}
}

int open_tty(char* tty)
{
  // create a new console
  int fd= open(tty, O_RDWR | O_SYNC);
  if (fd<0) {
    loge("Can't open %s", tty);
    return -1;
  }
  return fd;

}

int release_display(char *tty)
{
  int fd = open_tty(tty);
  int err = ioctl(fd, VT_RELDISP, (void*)1);
  if( err < 0)
    loge("ioctl(%d, VT_RELDISP, 1) failed %d \n",fd, errno);

  // to make sure that we are in text mode
  err = ioctl(fd, KDSETMODE, (void*) KD_TEXT);
  if (err<0) {
    loge("ioctl(%d, KDSETMODE, ...) failed, err %d \n", fd, err);
  }
  struct vt_stat vs;
  err = ioctl(fd, VT_GETSTATE, &vs);
  if (err<0) {
    loge("ioctl(%d, VT_GETSTATE, ...) failed, err %d\n", fd, err );
  }
  
  close(fd);
  return 0;
}

int acquire_display(char* tty)
{
  int err ;
  int vtnum = 7;
  int fd = open_tty(tty);
  // switch to console 7 (which is what X normaly uses)
  loge("switch to graphics mode\n");
  do {
    err = ioctl(fd, VT_ACTIVATE, (void*)vtnum);
  } while(err < 0 && errno == EINTR);
  if (err<0) {
    loge("ioctl VT_ACTIVATE failed, err= %d\n", errno);
  }

  do {
    err = ioctl(fd, VT_WAITACTIVE, (void*)vtnum);
  } while(err < 0 && errno == EINTR);
  if (err<0) {
    loge("ioctl(%d, VT_WAITACTIVE, ...) failed, %d %d for %d\n",
        fd, err, errno, vtnum);
  }

  // open the new console
  close(fd);
  fd = open_tty(tty);

//reopen, since tty has changed
  // switch to graphic mode
  err = ioctl(fd, KDSETMODE, (void*)KD_GRAPHICS);
  if( err < 0 )
    loge("ioctl(%d, KDSETMODE, KD_GRAPHICS) failed, err %d\n", fd, err);

  // set up signals so we're notified when the console changes
  // we can't use SIGUSR1 because it's used by the java-vm
  struct vt_mode vm;
  vm.mode = VT_PROCESS;
  vm.waitv = 0;
  vm.relsig = SIGREL;
  vm.acqsig = SIGACQ;
  vm.frsig = 0;
  err = ioctl(fd, VT_SETMODE, &vm);
  if (err<0) {
    loge("ioctl(%d, VT_SETMODE, ...) failed, %d\n \
        can't switch to VT_MODE\n", fd, errno);
  }

  // get the current console
  struct vt_stat vs;
  err = ioctl(fd, VT_GETSTATE, &vs);
  if (err<0) {
    loge("ioctl(%d, VT_GETSTATE, ...) failed, err %d\n", fd, err );
  }

}

int main(){

  return 0;
}
